#include "MOD_DEV_HEADER.h"



void do_UPTIME		(SUser *me, char tail[TAILSIZE]);
void do_LIST 		(SUser *me, char tail[TAILSIZE]);
void do_USRLIST 	(SUser *me, char tail[TAILSIZE]);
void do_TABLESLIST 	(SUser *me, char tail[TAILSIZE]);
void do_QUIT 		(SUser *me, char tail[TAILSIZE]);
void do_PART 		(SUser *me, char tail[TAILSIZE]);
void do_SETTOPIC	(SUser *me, char tail[TAILSIZE]);
void do_TOPIC 		(SUser *me, char tail[TAILSIZE]);
void do_NICK 		(SUser *me, char tail[TAILSIZE]);
void do_PRIVMSG 	(SUser *me, char tail[TAILSIZE]);
void do_JOIN 		(SUser *me, char tail[TAILSIZE]);
void do_PV 			(SUser *me, char tail[TAILSIZE]);

/* entry */
void aures_init (SModule* module)
{ 
	MODULE_NAME		(module,	"User Commands"			);
	MODULE_VERSION	(module,	"1.0 beta"				);
	MODULE_DESC		(module,	"Server user commands"	);
	MODULE_AUTHOR	(module, 	"Goundy"				);

	AddCommand ("uptime", do_UPTIME, LEVEL_ALL);
	AddCommand ("list", do_LIST, LEVEL_ALL);
	AddCommand ("usrlist", do_USRLIST, LEVEL_ALL);
	AddCommand ("tableslist", do_TABLESLIST, LEVEL_ALL);
	AddCommand ("quit", do_QUIT, LEVEL_ALL);
	AddCommand ("part", do_PART, LEVEL_ALL);
	AddCommand ("settopic", do_SETTOPIC, LEVEL_ALL);
	AddCommand ("topic", do_TOPIC, LEVEL_ALL);
	AddCommand ("nick", do_NICK, LEVEL_NONE);
	AddCommand ("privmsg", do_PRIVMSG, LEVEL_ALL);
	AddCommand ("join", do_JOIN, LEVEL_ALL);
	AddCommand ("pv", do_PV, LEVEL_ALL);
}

/* clean up */
void aures_cleanup (void)
{
	DelCommand ("uptime");
	DelCommand ("list");
	DelCommand ("usrlist");
	DelCommand ("tableslist");
	DelCommand ("quit");
	DelCommand ("settopic");
	DelCommand ("topic");
	DelCommand ("nick");
	DelCommand ("privmsg");
	DelCommand ("join");
	DelCommand ("pv");
}


/* Commands */



void do_SETTOPIC ( SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  STable *tab = NULL;
 char tname[TABLENAMESIZE], *ptr = NULL;
 int gard;

	gard = sscanf (tail, "%32s", (char*)&tname);
	if (gard == 1){
		tab = Htb_SearchTables (tablestb, tname);
			if (tab == NULL){
				gard = SendToUser (me->id, "%d %s", ENUM_418, ENOSUCHTABLE);
					if (gard == -2){
						do_KILL (me, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
			else
			if (tab->owner != me->id){
				gard = SendToUser (me->id, "%d %s", ENUM_414, ENOTANOWNER);
					if (gard == -2){
						do_KILL (me, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
			else
			{
				ptr = strchr (tail, ' ');
				if ((ptr)&&(ptr++)){
					strcpy (tab->desc, ptr);
				}
				else
					settozero (tab->desc);
				SendToTable (tab, "TOPIC %s %s", tname, tab->desc);
			}
	}
	else{
		gard = SendToUser (me->id, "bad request");
			if (gard == -2){
				do_KILL (me, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}

void do_TOPIC (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  STable *tab = NULL;
  int gard;

	tab = Htb_SearchTables (tablestb, tail);
	if (tab != NULL){
		if (Htb_SearchBlackList (tab->blacklist, me->user)){
			gard = SendToUser (me->id, "You are banned from this table\r\n");
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
		else
		{
			gard = SendToUser (me->id, "TOPIC %s %s", tail, tab->desc);
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
	}
	else
	{
		gard = SendToUser (me->id, "%d %s", ENUM_418, ENOSUCHTABLE);
			if (gard == -2){
				do_KILL (me, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}

void do_TABLESLIST ( SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  int i, gard=0;

	for (i = 0; i < tablestb->length; i++){
		if (tablestb->table[i]!= NULL)
			gard = SendToUser (me->id, "TABLESLIST %s %s\r\n", tablestb->table[i]->name, tablestb->table[i]->desc);
				if (gard == -2){
					do_KILL (me, "broken pipe");
					return;
				}
				if (gard == -1){
					printf("error send()\n");
					return;
				}
	}
}

void do_USRLIST ( SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  STable *tab = NULL;
  int i, gard;

	tab = Htb_SearchTables (tablestb, tail);
	if (tab != NULL){
		if (Htb_SearchBlackList(tab->blacklist, me->user)){
			gard = SendToUser (me->id, "You are banned from this table\r\n");
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
		else
		{
			for (i = 0; i < tab->tableusers->length; i++){
				if (tab->tableusers->table[i] != NULL){
					gard = SendToUser (me->id, "USRLIST %s\r\n", tab->tableusers->table[i]->user);
						if (gard == -2){
							do_KILL (me, "broken pipe");
							return;
						}
						if (gard == -1){
							printf("error send()\n");
							return;
						}
				}
			}
		}
	}
	else{
		gard = SendToUser (me->id, "%d %s\r\n", ENUM_418, ENOSUCHTABLE);
			if (gard == -2){
				do_KILL (me, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}


void do_LIST (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
	int i, gard;

	for (i=0; i < userstb->length; i++){
		if (userstb->table[i] != NULL){
			gard = SendToUser (me->id, "LIST %s\r\n", userstb->table[i]->nick);
				if (gard == -2){
					do_KILL (me, "broken pipe");
					return;
				}
				if (gard == -1){
					printf("error send()\n");
					return;
				}
		}
	}
}

void do_JOIN (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  STable *tab = NULL;
  STableUsers *nts = NULL;
  SUserTables *nut = NULL;
  int gard;

	tab = Htb_SearchTables (tablestb, tail);
		if (tab == NULL){
			gard = SendToUser (me->id, "%d %s\r\n", ENUM_418, ENOSUCHTABLE);
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
		else
		{
			if (Htb_SearchBlackList (tab->blacklist, me->user)){
				gard = SendToUser (me->id, "You are banned from this table\r\n");
					if (gard == -2){
						do_KILL (me, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
			else
			{
			nts = malloc (sizeof (STableUsers));
			strcpy (nts->user, me->nick);
			Htb_AddTableUsers (nts, &tab->tableusers);

			nut = malloc (sizeof (SUserTables));
			strcpy (nut->name, tab->name);
			Htb_AddUserTables (nut, &me->usertables);

			SendToTable (tab, "JOIN %s %s %s %s", tail, me->nick, me->user, me->host);
			gard = SendToUser (me->id, "TOPIC %s %s", tab->name, tab->desc);
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
			}
		}
}

void do_PV ( SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  SUser* to = NULL;
 char nick[NICKSIZE], *ms = NULL;
 int gard;

	gard = sscanf (tail, "%16s", nick);
		if (gard == 1){
			if (((ms = strchr(tail, ' ')) != NULL) && (ms++)){
				to = Htb_SearchUser (userstb, nick);
					if (to != NULL){
						gard = SendToUser (to->id, "PV %s %s %s %s", me->nick, me->user, me->host, ms);
							if (gard == -2){
								do_KILL (me, "broken pipe");
							}
							if (gard == -1)
								printf("error send()\n");
					}
					else
					{
						gard = SendToUser (to->id, "No such nickname\r\n");
							if (gard == -2){
								do_KILL (me, "broken pipe");
							}
							if (gard == -1)
								printf("error send()\n");
					}
			}
		}
}

void do_NICK (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
  int i, gard;


	if (NickIsValid ((char*)tail) == 0){
		strncpy (me->nick, tail, NICKSIZE);

		for (i=0; i < me->usertables->length; i++)
			if (me->usertables->table[i] != NULL)
			   SendToTable (Htb_SearchTables(tablestb, me->usertables->table[i]->name), "%s is known as %s", me->user, me->nick);
	}
	else
	{
		gard = SendToUser (me->id, "%d %s", ENUM_402, EINVALIDNICK);
			if (gard == -2){
				do_KILL (me, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}

void do_PRIVMSG (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
 char tabname[TABLENAMESIZE], *ptr = NULL;
 int err;
 STable *tbl = NULL;

	err = sscanf (tail, "%32s", tabname);
		if (err != 1){
			/* error */
			err = SendToUser (me->id, "bad request");
				if (err == -2){
					do_KILL (me, "broken pipe");
				}
				if (err == -1)
					printf("error send()\n");
			return;
		}

	ptr = strchr (tail, ' ') + 1;
		if (ptr == NULL){
			/*error*/
			return;
		}

	tbl = Htb_SearchTables (tablestb, tabname);
		if (tbl == NULL){
			err = SendToUser (me->id, "no such channel");
				if (err == -2){
					do_KILL (me, "broken pipe");
				}
				if (err == -1)
					printf("error send()\n");
		}
		else
		{
			if (Htb_SearchTableUsers(tbl->tableusers, me->nick))
				SendToTable (tbl, "PRIVMSG %s %s %s", tabname, me->nick, ptr);
			else
			{
				err = SendToUser (me->id, "You aren't on the table\r\n");
					if (err == -2){
						do_KILL (me, "broken pipe");
					}
					if (err == -1)
						printf("error send()\n");
			}
		}
}

void do_QUIT (SUser *me, char tail[TAILSIZE])
/*
	
*/
{
 int i;
 unsigned int hash;

	for (i=0; i < me->usertables->length; i++){
		if (me->usertables->table[i] != NULL){
			hash = hash_string (me->usertables->table[i]->name, me->usertables->length);
			Htb_RemoveTableUsers (&tablestb->table[hash]->tableusers, me->nick);
			SendToTable (tablestb->table[hash], "QUIT %s %s", me->nick, tail);
		}
	}

	CloseSocket (me->id);
	Htb_DestroyUserTables (&me->usertables);
	Htb_RemoveUser (&userstb, me->nick);
	me = NULL;
}

/* server admin functions */


void do_UPTIME (SUser* me, char tail[TAILSIZE]){

 time_t now;
 time_t stamp;
 struct tm *tmm;
 char suptime[32];
 size_t err;
 int gard;

	now = time (NULL);
		if (now == -1){
			gard = SendToUser (me->id, "Erreur temps\r\n");
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
		else
		{
			stamp = difftime (now, starttime);
			tmm = gmtime (&stamp);
				if (tmm == NULL){
					printf ("gmtime error\n");
					return;
				}

 			err = strftime (suptime, sizeof (suptime), "%X", tmm);

			gard = SendToUser (me->id, "UPTIME %s\r\n", suptime);
				if (gard == -2){
					do_KILL (me, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
}


